1 using System;
2 using
System.Collections;
3 using
System.Collections.Generic;
4 using
System.Diagnostics;
5 using
System.Net;
6 using
ExitGames.Client.Photon;
7 using
UnityEngine;
8 using
Debug = UnityEngine.Debug;
9
10
11 #
if UNITY_EDITOR || (!UNITY_ANDROID && !UNITY_IPHONE && !UNITY_PS3 && !UNITY_WINRT)
12
13 using
System.Net.Sockets;
14
15 ///
<summary>Uses C# Socket class from System.Net.Sockets (as Unity usually does).</summary>
16 ///
<remarks>Incompatible with Windows 8 Store/Phone API.</remarks>
17 public
class PingMonoEditor : PhotonPing
18 {
19     
private Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
20
21     
public override bool StartPing(string ip)
22     {
23         
base.Init();
24
25         
try
26         {
27             sock.ReceiveTimeout =
5000;
28             sock.Connect(ip,
5055);
29
30             PingBytes[PingBytes.Length -
1] = PingId;
31             sock.Send(PingBytes);
32             PingBytes[PingBytes.Length -
1] = (byte)(PingId - 1);
33         }
34         
catch (Exception e)
35         {
36             sock =
null;
37             Console.WriteLine(e);
38         }
39
40         
return false;
41     }
42
43     
public override bool Done()
44     {
45         
if (this.GotResult || sock == null)
46         {
47             
return true;
48         }
49
50         
if (sock.Available <= 0)
51         {
52             
return false;
53         }
54
55         
int read = sock.Receive(PingBytes, SocketFlags.None);
56         
//Debug.Log("Got: " + SupportClass.ByteArrayToString(PingBytes));
57         
bool replyMatch = PingBytes[PingBytes.Length - 1] == PingId && read == PingLength;
58         
if (!replyMatch) Debug.Log("ReplyMatch is false! ");
59
60
61         
this.Successful = read == PingBytes.Length && PingBytes[PingBytes.Length - 1] == PingId;
62         
this.GotResult = true;
63         
return true;
64     }
65
66     
public override void Dispose()
67     {
68         
try
69         {
70             sock.Close();
71         }
72         
catch
73         {
74         }
75         sock =
null;
76     }
77
78 }
79 #endif

80
81
82
83 public
class PhotonPingManager
84 {
85     
public bool UseNative;
86     
public static int Attempts = 5;
87     
public static bool IgnoreInitialAttempt = true;
88     
public static int MaxMilliseconsPerPing = 800; // enter a value you're sure some server can beat (have a lower rtt)
89
90
91     
public Region BestRegion
92     {
93         
get
94         {
95             Region result =
null;
96             
int bestRtt = Int32.MaxValue;
97             
foreach (Region region in PhotonNetwork.networkingPeer.AvailableRegions)
98             {
99                 Debug.Log(
"BestRegion checks region: " + region);
100                 
if (region.Ping != 0 && region.Ping < bestRtt)
101                 {
102                     bestRtt = region.Ping;
103                     result = region;
104                 }
105             }
106
107             
return (Region)result;
108         }
109     }
110
111     
public bool Done { get { return this.PingsRunning == 0; } }
112     
private int PingsRunning;
113
114
115     ///
<remarks>
116     ///
Affected by frame-rate of app, as this Coroutine checks the socket for a result once per frame.
117     ///
</remarks>
118     
public IEnumerator PingSocket(Region region)
119     {
120         region.Ping = Attempts*MaxMilliseconsPerPing;
121
122         
this.PingsRunning++; // TODO: Add try-catch to make sure the PingsRunning are reduced at the end and that the lib does not crash the app
123         PhotonPing ping;
124         
//Debug.Log("PhotonHandler.PingImplementation " + PhotonHandler.PingImplementation);
125         
if (PhotonHandler.PingImplementation == typeof(PingNativeDynamic))
126         {
127             Debug.Log(
"Using constructor for new PingNativeDynamic()"); // it seems on android, the Activator can't find the default Constructor
128             ping =
new PingNativeDynamic();
129         }
130         
else
131         {
132             ping = (PhotonPing)Activator.CreateInstance(PhotonHandler.PingImplementation);
133         }
134
135         
//Debug.Log("Ping is: " + ping + " type " + ping.GetType());
136
137         
float rttSum = 0.0f;
138         
int replyCount = 0;
139
140
141         
// PhotonPing.StartPing() requires a plain IP address without port (on all but Windows 8 platforms).
142         
// So: remove port and do the DNS-resolving if needed
143         
string cleanIpOfRegion = region.HostAndPort;
144         
int indexOfColon = cleanIpOfRegion.LastIndexOf(':');
145         
if (indexOfColon > 1)
146         {
147             cleanIpOfRegion = cleanIpOfRegion.Substring(
0, indexOfColon);
148         }
149         cleanIpOfRegion = ResolveHost(cleanIpOfRegion);
150         
//Debug.Log("Resolved and port-less IP is: " + cleanIpOfRegion);
151
152
153         
for (int i = 0; i < Attempts; i++)
154         {
155             
bool overtime = false;
156             Stopwatch sw =
new Stopwatch();
157             sw.Start();
158
159             
try
160             {
161                 ping.StartPing(cleanIpOfRegion);
162             }
163             
catch (Exception e)
164             {
165                 Debug.Log(
"catched: " + e);
166                 
this.PingsRunning--;
167                 
break;
168             }
169
170
171             
while (!ping.Done())
172             {
173                 
if (sw.ElapsedMilliseconds >= MaxMilliseconsPerPing)
174                 {
175                     overtime =
true;
176                     
break;
177                 }
178                 
yield return 0; // keep this loop tight, to avoid adding local lag to rtt.
179             }
180             
int rtt = (int)sw.ElapsedMilliseconds;
181
182
183             
if (IgnoreInitialAttempt && i == 0)
184             {
185                 
// do nothing.
186             }
187             
else if (ping.Successful && !overtime)
188             {
189                 rttSum += rtt;
190                 replyCount++;
191                 region.Ping = (
int)((rttSum) / replyCount);
192                 
//Debug.Log("region " + region.Code + " RTT " + region.Ping + " success: " + ping.Successful + " over: " + overtime);
193             }
194
195             
yield return new WaitForSeconds(0.1f);
196         }
197
198         
this.PingsRunning--;
199
200         
//Debug.Log("this.PingsRunning: " + this.PingsRunning + " this debug: " + ping.DebugString);
201         
yield return null;
202     }
203
204 #
if UNITY_WINRT && !UNITY_EDITOR
205
206     
public static string ResolveHost(string hostName)
207     {
208         
return hostName;
209     }
210
211 #
else
212
213     ///
<summary>
214     ///
Attempts to resolve a hostname into an IP string or returns empty string if that fails.
215     ///
</summary>
216     ///
<param name="hostName">Hostname to resolve.</param>
217     ///
<returns>IP string or empty string if resolution fails</returns>
218     
public static string ResolveHost(string hostName)
219     {
220         
try
221         {
222             IPAddress[] address = Dns.GetHostAddresses(hostName);
223
224             
if (address.Length == 1)
225             {
226                 
return address[0].ToString();
227             }
228
229             
// if we got more addresses, try to pick a IPv4 one
230             
for (int index = 0; index < address.Length; index++)
231             {
232                 IPAddress ipAddress = address[index];
233                 
if (ipAddress != null)
234                 {
235                     
string ipString = ipAddress.ToString();
236                     
if (ipString.IndexOf('.') >= 0)
237                     {
238                         
return ipString;
239                     }
240                 }
241             }
242         }
243         
catch (System.Exception e)
244         {
245             Debug.Log(
"Exception caught! " + e.Source + " Message: " + e.Message);
246         }
247
248         
return String.Empty;
249     }
250 #endif
251 }


Uses C# Socket class from System.Net.Sockets (as Unity usually does).

Incompatible with Windows 8 StorePhone API.

Debug.Log("Got: " + SupportClass.ByteArrayToString(PingBytes));

public static int MaxMilliseconsPerPing = 800; enter a value you're sure some server can beat (have a lower rtt)

Affected by frame-rate of app, as this Coroutine checks the socket for a result once per frame.

this.PingsRunning++; TODO: Add try-catch to make sure the PingsRunning are reduced at the end and that the lib does not crash the app

Debug.Log("PhotonHandler.PingImplementation " + PhotonHandler.PingImplementation);

Debug.Log("Using constructor for new PingNativeDynamic()"); it seems on android, the Activator can't find the default Constructor

Debug.Log("Ping is: " + ping + " type " + ping.GetType());

PhotonPing.StartPing() requires a plain IP address without port (on all but Windows 8 platforms).

So: remove port and do the DNS-resolving if needed

Debug.Log("Resolved and port-less IP is: " + cleanIpOfRegion);

yield return 0; keep this loop tight, to avoid adding local lag to rtt.

do nothing.

Debug.Log("region " + region.Code + " RTT " + region.Ping + " success: " + ping.Successful + " over: " + overtime);

Debug.Log("this.PingsRunning: " + this.PingsRunning + " this debug: " + ping.DebugString);

Attempts to resolve a hostname into an IP string or returns empty string if that fails.

Hostname to resolve.

IP string or empty string if resolution fails

if we got more addresses, try to pick a IPv4 one




Trò chơi Tic-Tac-Toe, game đánh caro full source code 53.568 lượt xem

Gõ tìm kiếm nhanh...